#include "cargadorDeArchivos.h"

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
using namespace std;
#define NOMBRE_ARCHIVO_DICCIONARIO "diccionario.txt"
#define NOMBRE_ARCHIVO_APARICIONES "aparicionesRelevantes.txt"
#define NOMBRE_ARCHIVO_TRIGRAMAS "trigramas.txt"
#define SEPARADOR_PRIMERAS_PALABRAS 'P'
#define SEPARADOR_SEGUNDAS_PALABRAS 'S'
#define SEPARADOR_TERCERAS_PALABRAS 'T'
#define SEPARADOR_PALABRA_FRECUENCIA 'F'

void cargarDiccionarioAMedias(diccionario_t* dic){
	FILE* archivoDiccionario = fopen(NOMBRE_ARCHIVO_DICCIONARIO ,"r");

	int id;
	termino_t termino;
	char lineaDic_c[40];

	string palabra;

	while(!feof(archivoDiccionario)){
		fscanf(archivoDiccionario, "%[^\n]\n", lineaDic_c);
		vector<string> vecDic;
		split(lineaDic_c, ' ', &vecDic);
		id = atoi(vecDic.at(0).c_str());
		palabra = vecDic.at(1);

		termino_t termino;
		termino.index = id;
		termino.bitSetDeFragmentos = nullptr;

		dic->mapa.insert(pair<string, termino_t>(palabra, termino));
	}
	fclose(archivoDiccionario);
}

void cargarDiccionario(
		diccionario_t* dic,
		diccionarioPorIndice_t* dicPorIndice,
		set<int>* testSet){

	ofstream log("logDeCArgarDiccionario.txt");
	int i = 0;

	dic->total = 0;
	FILE* archivoDiccionario = fopen(NOMBRE_ARCHIVO_DICCIONARIO, "r");
	FILE* archivoApariciones = fopen(NOMBRE_ARCHIVO_APARICIONES, "r");
	int id, freq;
	string lineaAp, lineaDic;
	char lineaAp_c[2000000];
	char lineaDic_c[40];

	while(!dicPorIndice->empty())
		dicPorIndice->erase(dicPorIndice->begin());

	while((!feof(archivoDiccionario)) and (!feof(archivoApariciones))){
		fscanf(archivoDiccionario, "%[^\n]\n", lineaDic_c);
		fscanf(archivoApariciones, "%[^\n]\n", lineaAp_c);
		lineaAp = lineaAp_c;
		lineaDic = lineaDic_c;
		vector<string> vecDic;
		split(lineaDic, ' ', &vecDic);
		id = atoi(vecDic.at(0).c_str());

		termino_t termino;
		if(testSet->find(id) != testSet->end()){

			freq = atoi(vecDic.at(2).c_str());
			string palabra = vecDic.at(1);
			termino.index = id;
			termino.frecuencia = freq;

			vector<string> vectorAp;
			split(lineaAp, ' ', &vectorAp);


			//Le saco el indice y el '$'
		/*	if (i <= 2 ){
				cout<<"Numero del indice: "<<vectorAp[0]<<"\n";
				cout<<"Se indexan apariciones : "<<vectorAp[1]<<"\n";
				cout<<"Ultimo caracter: "<<vectorAp[vectorAp.size()-1]<<"\n";
				i++;
				int j;
				cout<<"Ingresar un nro para continuar: ";
				cin>>j;
				cout<<"\n";
			}
		*/

		/*	if ( id != atoi(vectorAp[0].c_str()) ){
				log<<"Esta mal con el indice: "<<id<<"  Indice leido: "<<vectorAp[0].c_str()<<"\n";
			}
			else {log<<"\n"<<"\n"<<"\n"<<"\n"<<"\n"<<"\n"<<"\n";}
		*/


			vectorAp.erase (vectorAp.begin());
			vectorAp.pop_back();
			vectorAp.pop_back();


		/*	if (i == 1 ){
				cout<<"Se indexan apariciones : "<<vectorAp[0]<<"\n";
				cout<<"Ultimo caracter: "<<vectorAp[vectorAp.size()-1]<<"\n";
				i++;
				int j;
				cout<<"Ingresar un nro para continuar: ";
				cin>>j;
				cout<<"\n";
			}
		*/
			termino.sonAparicones = (atoi(vectorAp[0].c_str()) == 1);


			termino.bitSetDeFragmentos = new bitset<180318>;


			termino.bitSetDeFragmentos->reset();


			for(size_t i = 1; i< vectorAp.size(); i++){
				(*(termino.bitSetDeFragmentos))[atoi(vectorAp.at(i).c_str())] = true;
			}
			if(! termino.sonAparicones) termino.bitSetDeFragmentos->flip();

			dic->mapa.insert(pair<string, termino_t>(palabra, termino));
			dicPorIndice->insert(pair<int, string>(id, palabra));
		}


		dic->total += freq;
	}
	fclose(archivoDiccionario);
	fclose(archivoApariciones);

}

void cargarPalabrasEIndicesEnDiccionarios(diccionario_t* dic,
										  diccionarioPorIndice_t* dicPorIndice,
										  set<int>* testSet){

	dic->total = 0;
	FILE* archivoDiccionario = fopen(NOMBRE_ARCHIVO_DICCIONARIO, "r");
	int id, freq;
	string lineaDic;
	char lineaDic_c[40];

	while(!feof(archivoDiccionario)){
		fscanf(archivoDiccionario, "%[^\n]\n", lineaDic_c);
		lineaDic = lineaDic_c;
		vector<string> vecDic;
		split(lineaDic, ' ', &vecDic);
		id = atoi(vecDic.at(0).c_str());

		termino_t termino;
		if(testSet->find(id) != testSet->end()){
			freq = atoi(vecDic.at(2).c_str());
			string palabra = vecDic.at(1);
			termino.index = id;
			termino.frecuencia = freq;
			termino.bitSetDeFragmentos = nullptr;

			dic->mapa.insert(pair<string, termino_t>(palabra, termino));
			dicPorIndice->insert(pair<int, string>(id, palabra));
		}


		dic->total += freq;
	}
	fclose(archivoDiccionario);
}





void cargarAparicionesEnDiccionario(diccionario_t* dic,
		  	  	  	  	  	  	  	diccionarioPorIndice_t* dicPorIndice,
									set<int>* testSet){


	FILE* archivoApariciones = fopen(NOMBRE_ARCHIVO_APARICIONES, "r");

	string lineaAp;
	char lineaAp_c[2000000];


	while(!feof(archivoApariciones)){
		fscanf(archivoApariciones, "%[^\n]\n", lineaAp_c);
		lineaAp = lineaAp_c;
		vector<string> vectorAp;
		split(lineaAp, ' ', &vectorAp);

		int id = atoi(vectorAp.at(0).c_str());

		if(testSet->find(id) != testSet->end()){
			//Le saco el indice, el '$' y el string vacio
			vectorAp.erase (vectorAp.begin());
			vectorAp.pop_back();
			vectorAp.pop_back();

			string palabraDeApariciones = (*dicPorIndice)[id];
			termino_t* termino = &(*dic).mapa[palabraDeApariciones];

			//Ahora en laposicion cero quedo el sonApariciones
			termino->sonAparicones = (atoi(vectorAp[0].c_str()) == 1);
			termino->bitSetDeFragmentos = new bitset<180318>;
			termino->bitSetDeFragmentos->reset();


			for(size_t i = 1; i< vectorAp.size(); i++){
				(*(termino->bitSetDeFragmentos))[atoi(vectorAp.at(i).c_str())] = true;
			}
			if(! termino->sonAparicones) termino->bitSetDeFragmentos->flip();
		}
	}
	fclose(archivoApariciones);
}

























//----------------
bool estaEnMapa2(int key, map<int, map<int, int> >* mapa){
	//for(map<int, map<int, int> >::iterator it = mapa->begin() ; it != mapa->end() ; ++it)
	//	if(it->first == key) return true;
	//return false;
	return (mapa->find(key) != mapa->end());
}

bool estaEnMapa3(int key, map<int, map<int, map<int, int> > >* mapa){
	//for(map<int, map<int, map<int, int> > >::iterator it = mapa->begin() ; it != mapa->end() ; ++it)
	//	if(it->first == key) return true;
	//return false;
	return (mapa->find(key) != mapa->end());
}


void agregar(mapaDeTrigramas_t* mapa, int pri, int seg, int ter, int freq){
	(*mapa)[pri][seg][ter] = freq;
/*
	if(estaEnMapa3(pri, mapa)){

		if(estaEnMapa2(seg, &(mapa->at(pri)))){
			mapa->at(pri).at(seg).insert(pair<int, int>(ter, freq));
			return;
		}
		else{
			map<int, int> newMapii;
			newMapii.insert( pair<int, int>(ter, freq) );
			mapa->at(pri).insert(pair<int, map<int, int> >(seg, newMapii));
			return;
		}
	}
	else{
		map<int, int> newMapii;
		newMapii.insert(pair<int, int>(ter, freq));
		map<int, map<int, int> > newMapim;
		newMapim.insert(pair<int, map<int, int> >(seg, newMapii));
		mapa->insert(pair<int, map<int, map<int, int> > >(pri, newMapim));
		return;
	}*/
}

// cada linea: p1-S2-p2-S3-p3-SPF-fr-S3-p3-SPF-fr-S3-p3-SPF-fr-S2-p2-S3-p3-SPF-fr-S3-p3-SPF-fr-S3-p3-SPF-fr-S1-

void cargarTrigramas(set<int>* testSet, mapaDeTrigramas_t* mapaDeTrigramas){
	FILE* archivoDeTrigramas = fopen(NOMBRE_ARCHIVO_TRIGRAMAS, "r");
	fgetc(archivoDeTrigramas);

	ofstream logDeFrecuencias("logDeFrecuencias.txt");



	int i = 0;

	cout<<"Va a entrar al while \n";

	char* linea = new char[74000000];

	while(!feof(archivoDeTrigramas)){
//CAMBIO A PTERO		vector< vector< string > > matrizSeparada;
		vector< vector< string >* > matrizSeparada;


		fscanf(archivoDeTrigramas, "%[^P]P", linea);

		vector<string> vectorSeparado;
		split(linea, SEPARADOR_SEGUNDAS_PALABRAS, &vectorSeparado);

		int primeraPalabra = atoi(vectorSeparado.at(0).c_str());

		if(testSet->find(primeraPalabra) != testSet->end()){
			int tam = vectorSeparado.size();

			for(int i = 1 ; i < tam ; i++){
//CAMBIO A PTERO				vector<string> veci;
//				split(vectorSeparado.at(i), SEPARADOR_TERCERAS_PALABRAS, &veci);
//				matrizSeparada.push_back(veci);
				//Aca debe tardar mucho tiempo copiando los datos

				vector<string>* veci = new vector<string>; //DESPUES DELETEAR ESTO, QUEDA CARGADO EN LA MATRIZ
				split(vectorSeparado.at(i), SEPARADOR_TERCERAS_PALABRAS, veci);
				matrizSeparada.push_back(veci);
			}

			int segundaPalabra;
			int terceraPalabra;
			int frecuencia;


			int cantidadDeVectores = matrizSeparada.size();

			for(int i = 0; i < cantidadDeVectores ; i++){
				vector<string>* x = matrizSeparada.at(i);
				segundaPalabra = atoi(x->at(0).c_str());

				for(size_t i = 1; i < x->size(); i++){
					vector<string> palabraVsFrecuencia;
					split(x->at(i), SEPARADOR_PALABRA_FRECUENCIA, &palabraVsFrecuencia);
					terceraPalabra = atoi(palabraVsFrecuencia.at(0).c_str());

					frecuencia = atoi(palabraVsFrecuencia.at(1).c_str());
					if (frecuencia > 3){
						agregar(mapaDeTrigramas, primeraPalabra, segundaPalabra, terceraPalabra, frecuencia);
					}
				}

				delete x;

			}
		}
	}

	delete[] linea;
	fclose(archivoDeTrigramas);

}

bool palabraApareceEnDiccionario(string palabra, diccionarioPorIndice_t* dicPorInd){
	for(map<int, string>::iterator it = dicPorInd->begin(); it != dicPorInd->end(); ++it){
		if(it->second == palabra) return true;
	}
	return false;
}


